package com.leador.http;

import android.content.Context;
import android.util.Log;

import com.leador.http.callback.EnitiyCallback;
import com.leador.http.callback.FenceCallBack;
import com.leador.http.callback.PointsCallback;
import com.leador.http.callback.ServiceCallback;
import com.leador.http.callback.TraceCallback;
import com.leador.listener.BaseTraceListener;
import com.leador.module.response.service.ServiceResult;
import com.leador.utils.Config;
import com.leador.utils.Utils;

import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.util.Map;
import java.util.UUID;

/**
 * Created by liuha on 2016/9/18.
 */
public class HttpCore extends Thread{
    private Context context;
    //是否加密
    private int encty;
    //请求路径
    private String BaseUrl;
    //请求方式 默认get
    private String requstType = "GET";
    //请求参数
    private String arg;
    //请求识别
    private String discern;
    //回调标识
    private int backFlag = 0;
    //是否批量上传
    private boolean  isPitch  = false;
    //上报文件名
    private File file;
    //上报参数
    private Map<String,String> params;
    /**
     * 上报的监听
     */
    private BaseTraceListener baseListener;

    public HttpCore(Context context){
        this.context = context;
    }
    @Override
    public void run() {
        super.run();
        boolean isNet = Utils.isNetworkConnected(context);
        if(!isNet){
            String errMsg ="{\"status\":10001,\"message\":\"无网络连接\"}";
            unActive(errMsg);
            return;
        }
        Log.e("BaseUrl is",BaseUrl+"?"+arg);
        String str = null;
        try {
            if(encty == 0){ //不加密
                str = unEncryptRequest();
            }else{
                //TODO 加密暂时未支持
            }
        } catch (Exception e) {
//            Log.e(Config.DEBUG,e.getMessage());
            e.printStackTrace();
        }

        //获得结果回调
        if(str == null){
            String msg = "{\"status\":10002,\"message\":\"内容为空\"}";
            unActive(msg);
            return;
        }
        //回调结果
        resoneseActive(str);
    }

    /**
     * 不加密
     * @return
     * @throws Exception
     */
    public  String unEncryptRequest() throws Exception {
        URL url;
        URLConnection connection = null;
        url = getBaseUrl();
        if (url != null) {
            connection = url.openConnection();
        }
        boolean requestParam = requestParams((HttpURLConnection) connection);
        String str = null;
        if (requestParam) {
            str = requst((HttpURLConnection) connection);
        }
        return str;
    }

    private static final int TIME_OUT = 10*10000000; //超时时间
    private static final String CHARSET = "utf-8"; //设置编码
    private static final String PREFIX = "--";
    private static final String LINE_END = "\r\n";
    public String requst(HttpURLConnection httpURLConnection) throws Exception{
        if(!(httpURLConnection instanceof  HttpURLConnection)){
            Log.e(Config.DEBUG,"HttpURLConnection类型错误");
        }
        InputStream inputStream = null;
        OutputStream outputStream;
        byte[] bytess;
        if(isPitch){ //上报
            String BOUNDARY = UUID.randomUUID().toString(); //边界标识 随机生成 String PREFIX = "--" , LINE_END = "\r\n";
            String CONTENT_TYPE = "multipart/form-data"; //内容类型
            httpURLConnection.setRequestProperty("Charset", CHARSET);//设置编码
            httpURLConnection.setRequestProperty("connection", "keep-alive");
            httpURLConnection.setRequestProperty("Content-Type", CONTENT_TYPE + ";boundary=" + BOUNDARY);
            httpURLConnection.setDoInput(true); //允许输入流
            httpURLConnection.setDoOutput(true); //允许输出流
            httpURLConnection.setUseCaches(false); //不允许使用缓存
            if(file!=null) {
                /** * 当文件不为空，把文件包装并且上传 */
                OutputStream outputSteam=httpURLConnection.getOutputStream();
                DataOutputStream dos = new DataOutputStream(outputSteam);
                StringBuffer sb = new StringBuffer();
                sb.append(LINE_END);
                if(params!=null){//根据格式，开始拼接文本参数
                    for(Map.Entry<String,String> entry:params.entrySet()){
                        sb.append(PREFIX).append(BOUNDARY).append(LINE_END);//分界符
                        sb.append("Content-Disposition: form-data; name=\"" + entry.getKey() + "\"" + LINE_END);
                        sb.append("Content-Type: text/plain; charset=" + CHARSET + LINE_END);
                        sb.append("Content-Transfer-Encoding: 8bit" + LINE_END);
                        sb.append(LINE_END);
                        sb.append(entry.getValue());
                        sb.append(LINE_END);//换行！
                    }
                }
                sb.append(PREFIX);//开始拼接文件参数
                sb.append(BOUNDARY); sb.append(LINE_END);
                /**
                 * 这里重点注意：
                 * name里面的值为服务器端需要key 只有这个key 才可以得到对应的文件
                 * filename是文件的名字，包含后缀名的 比如:abc.png
                 */
                sb.append("Content-Disposition: form-data; name=\"point_list\"; filename=\""+file.getName()+"\""+LINE_END);
                sb.append("Content-Type: application/octet-stream; charset="+CHARSET+LINE_END);
                sb.append(LINE_END);
                //写入文件数据
                dos.write(sb.toString().getBytes());
                InputStream is = new FileInputStream(file);
                byte[] bytes = new byte[1024];
                long totalbytes = file.length();
                long curbytes = 0;
                int len = 0;
                while((len=is.read(bytes))!=-1){
                    curbytes += len;
                    dos.write(bytes, 0, len);
                }
                is.close();
                dos.write(LINE_END.getBytes());
                byte[] end_data = (PREFIX+BOUNDARY+PREFIX+LINE_END).getBytes();
                dos.write(end_data);
                dos.flush();
                /**
                 * 获取响应码 200=成功
                 * 当响应成功，获取响应的流
                 */
                int code = httpURLConnection.getResponseCode();
                sb.setLength(0);
                inputStream = httpURLConnection.getInputStream();
            }
        }else{      //正常请求
                if ("GET".equals(requstType)) {
                    if (httpURLConnection.getResponseCode() == 200) {
                        inputStream = httpURLConnection.getInputStream();
                    }
                } else if ("POST".equals(requstType)) {
                    httpURLConnection.setDoOutput(true);
                    outputStream = httpURLConnection.getOutputStream();
                    bytess = this.arg.getBytes();
                    outputStream.write((bytess));
                    outputStream.flush();
                    outputStream.close();
                    inputStream = httpURLConnection.getInputStream();
                }
        }
        String str = Utils.getString(inputStream);
        return  str;
    };

    private boolean requestParams(HttpURLConnection httpURLConnection) {
        try {
            httpURLConnection.setRequestMethod(requstType);
            httpURLConnection.setConnectTimeout(5000);
            httpURLConnection.setReadTimeout(5000);
            return true;
        } catch (IOException localIOException) {
            Log.e(Config.DEBUG,"init HttpURLConnection  failed");
        }
        return false;
    }


    public void unActive(String msg){
        if("service".equals(discern)){
            ServiceCallback.serviceCallBack(0,msg);
        }

        if("entity".equals(discern)){
            EnitiyCallback.entityCallBack(0,msg);
        }

        if("gethistory".equals(discern)){
            TraceCallback.traceCallBack(0,msg);
        }


        if ("track".equals(discern)) {
            TraceCallback.traceCallBack(0,msg);
            return;
        }

        if ("geofence".equals(discern)) {
            FenceCallBack.fenceCallBack(0,msg);
            return;
        }

        if("point".equals(discern)){ //单个轨迹
            PointsCallback.pointCallBack(0,msg);
            return;
        }

        if("points".equals(discern)){  //多个轨迹
            PointsCallback.pointCallBack(1,msg);
            return;
        }

        if(baseListener != null){
            baseListener.failure(msg);
        }
    }

    public void resoneseActive(String msg){
        if("service".equals(discern)){
            ServiceCallback.serviceCallBack(backFlag,msg);
        }

        if("entity".equals(discern)){
            EnitiyCallback.entityCallBack(backFlag,msg);
        }

        if("gethistory".equals(discern)){
            TraceCallback.traceCallBack(backFlag,msg);
        }

        if ("track".equals(discern)) {
            TraceCallback.traceCallBack(backFlag,msg);
            return;
        }

        if ("geofence".equals(discern)) {
            FenceCallBack.fenceCallBack(backFlag,msg);
            return;
        }

        if("point".equals(discern)){ //单个轨迹
            PointsCallback.pointCallBack(backFlag,msg);
            return;
        }

        if("points".equals(discern)){  //多个轨迹
            PointsCallback.pointCallBack(backFlag,msg);
            return;
        }

        if(baseListener != null){
            baseListener.jsonToObject(msg);
        }
    }

    private URL getBaseUrl(){
        URL url = null;
        try {
            if("GET".equals(requstType)){
                url = new URL(this.BaseUrl + "?" + arg);
                return url;
            }
            if("POST".equals(requstType)){
                url  = new URL(this.BaseUrl);
                return url;
            }
        } catch (MalformedURLException e) {
            e.printStackTrace();
            Log.e(Config.DEBUG,"creates socket new URL instance failed");
        }
        return null;
    }

    //--------------------set property

    public void setEncty(int encty) {
        this.encty = encty;
    }

    public void setBaseUrl(String baseUrl) {
        this.BaseUrl = baseUrl;
    }

    public void setRequstType(String requstType) {
        this.requstType = requstType;
    }

    public void setArg(String arg) {
        this.arg = arg;
    }

    public void setDiscern(String discern) {
        this.discern = discern;
    }

    public void setBackFlag(int backFlag) {
        this.backFlag = backFlag;
    }

    public void setFile(File file) {
        this.file = file;
    }

    public void setPitch(boolean pitch) {
        isPitch = pitch;
    }

    public void setParams(Map<String, String> params) {
        this.params = params;
    }

    public void setBaseListener(BaseTraceListener baseListener) {
        this.baseListener = baseListener;
    }
}
